import 'dart:convert';

import 'package:dio/dio.dart';

enum HttpMethod {
  none,
  get,
  post,
}

typedef PreprocessHttpResponseBodyBlock = Future<dynamic> Function(
    dynamic rawData);
typedef CustomTransformHttpResponseDataBlock = Future<dynamic> Function(
    dynamic rawData, $HttpResponse result);

class $HttpResponse<T> {
  $HttpResponse({this.errorCode = 0, this.success = true, this.message = ''});

  static Future<$HttpResponse<T>> fromResponse<T>(
      Response httpResponse,
      PreprocessHttpResponseBodyBlock? responsePreprocessor,
      CustomTransformHttpResponseDataBlock? dataTransformer) async {
    $HttpResponse response = $HttpResponse<T>();
    response.httpResponse = httpResponse;
    response.responsePreprocessor = responsePreprocessor;
    response.dataTransformer = dataTransformer;
    await response.preprocessResponse();
    await response.parseResponse();
    return response as $HttpResponse<T>;
  }

  $HttpResponse.errorResponse({int errorCode = -1, String message = '请求失败'}) {
    this.success = false;
    this.errorCode = errorCode;
    this.message = message;
  }

  /// 原始响应结果
  Response? httpResponse;

  /// 原始body
  dynamic get httpBody => _processedHttpBody ?? httpResponse?.data;

  CustomTransformHttpResponseDataBlock? dataTransformer;
  PreprocessHttpResponseBodyBlock? responsePreprocessor;

  int errorCode = 0;
  bool success = true;
  String message = '';

  /// 解析后响应数据
  T? _data;

  T? get data {
    final _tData = (_data ?? rawData) ?? this.httpBody;
    if (success != true || _tData is! T) {
      return null;
    }
    return _tData;
  }

  set data(T? data) {
    _data = data;
  }

  /// 未处理的data原始字段数据
  /// {"success": true, "data":{}}
  dynamic rawData;

  dynamic _processedHttpBody;

  Future preprocessResponse() async {
    if (responsePreprocessor != null) {
      _processedHttpBody = responsePreprocessor!(this.httpResponse?.data);
    }
  }

  Future parseResponse() async {
    try {
      if (httpBody is String) {
        rawData = json.decode(httpBody);
      } else {
        success = false;
      }
    } catch (e) {
      rawData = httpBody;
      success = false;
      message = e.toString();
    }
  }
}

class $HttpErrorCode {
  static final int unknown = -1;
  static final int network = -2000;
  static final int response = -1000;
  static final int success = 200;
}
